package com.ssy.lingxi.platform.template.service.serviceimpl.adorn;

import cn.hutool.core.collection.CollectionUtil;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.product.PriceTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.platform.template.service.constant.SelectStatusEnum;
import com.ssy.lingxi.platform.template.service.entity.adorn.PlatformTemplateAdorn;
import com.ssy.lingxi.platform.template.service.entity.door.MemberLogistics;
import com.ssy.lingxi.platform.template.service.entity.door.MemberProcess;
import com.ssy.lingxi.platform.template.service.entity.door.MemberShop;
import com.ssy.lingxi.platform.template.service.entity.door.QMemberShop;
import com.ssy.lingxi.platform.template.service.model.bo.CategoryBO;
import com.ssy.lingxi.platform.template.service.model.bo.WebPlatformBO;
import com.ssy.lingxi.platform.template.service.model.dto.adorn.WebPlatformTemplateAdornDTO;
import com.ssy.lingxi.platform.template.service.model.dto.common.TemplateIdDTO;
import com.ssy.lingxi.platform.template.service.model.dto.web.RecommendDTO;
import com.ssy.lingxi.platform.template.service.model.vo.adorn.*;
import com.ssy.lingxi.platform.template.service.repository.MemberLogisticsRepository;
import com.ssy.lingxi.platform.template.service.repository.MemberProcessRepository;
import com.ssy.lingxi.platform.template.service.repository.MemberShopRepository;
import com.ssy.lingxi.platform.template.service.repository.PlatformTemplateAdornRepository;
import com.ssy.lingxi.platform.template.service.service.adorn.WebPlatformService;
import com.ssy.lingxi.product.api.feign.ICommodityFeign;
import com.ssy.lingxi.product.api.model.request.MemberRequest;
import com.ssy.lingxi.product.api.model.response.store.StoreResponse;
import com.ssy.lingxi.search.api.feign.ITemplateFeign;
import com.ssy.lingxi.search.api.model.request.TemplateCommoditySearchRequest;
import com.ssy.lingxi.search.api.model.response.BrandResponse;
import com.ssy.lingxi.search.api.model.response.CommoditySearchResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toList;

/**
 * 模板装修 - WEB平台首页装修 - 业务实现层
 *
 * @author fhj
 * @version 2.0.0
 * @date 2021/04/20
 */
@Slf4j
@Service
public class WebPlatformServiceImpl implements WebPlatformService {

    @Resource
    private PlatformTemplateAdornRepository platformTemplateAdornRepository;
    @Resource
    private ITemplateFeign templateFeign;
    @Resource
    private MemberLogisticsRepository memberLogisticsRepository;
    @Resource
    private MemberProcessRepository memberProcessRepository;
    @Resource
    private ICommodityFeign commodityFeign;
    @Resource
    private JPAQueryFactory jpaQueryFactory;

    /**
     * 保存WEB平台首页装修
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    @Transactional
    public Wrapper<Void> save(WebPlatformTemplateAdornDTO dto, UserLoginCacheDTO sysUser) {
        PlatformTemplateAdorn adorn = platformTemplateAdornRepository.findByTemplateId(dto.getTemplateId());
        adorn = adorn == null ? new PlatformTemplateAdorn() : adorn;
        adorn.setTemplateId(dto.getTemplateId());
        adorn.setList(dto.getList());
        platformTemplateAdornRepository.saveAndFlush(adorn);
        return Wrapper.success();
    }

    /**
     * 获取WEB平台首页装修
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<List<WebPlatformBO>> find(TemplateIdDTO dto) {
        PlatformTemplateAdorn adorn = platformTemplateAdornRepository.findByTemplateId(dto.getTemplateId());
        if (adorn == null) {
            return Wrapper.success(null);
        }
        return Wrapper.success(adorn.getList());
    }

    /**
     * 获取商品列表
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<PageData<GoodsVO>> findGoodsList(RecommendDTO dto) {
        //拿到商品ID集合
        List<Long> goodsIds = dto.getGoodsIdList() != null && CollectionUtil.isNotEmpty(dto.getGoodsIdList()) ? dto.getGoodsIdList() : null;

        /*
            调用搜索服务 -> 查询商品信息接口:
               0.未选择 根据商品ID查出不包含的商品
               1.已选择 根据商品ID查出包含的商品
               2.所有  查出所有
        */
        Wrapper<PageData<CommoditySearchResponse>> wrapper = null;
        if (dto.getType().equals(SelectStatusEnum.UNSELECTED.getCode())) {
            TemplateCommoditySearchRequest request = new TemplateCommoditySearchRequest();
            request.setCurrent(dto.getCurrent());
            request.setPageSize(dto.getPageSize());
            request.setShopId(dto.getShopId());
            request.setCategoryId(dto.getCategoryId());
            request.setBrandId(dto.getBrandId());
            request.setMemberName(dto.getSupplyName());
            request.setName(dto.getGoodsName());
            request.setIdNotInList(goodsIds);
            request.setPriceTypeList(Stream.of(PriceTypeEnum.Cash.getCode()).collect(Collectors.toList()));
            wrapper = templateFeign.searchCommodityList(request);
        }
        if (dto.getType().equals(SelectStatusEnum.SELECTED.getCode())) {
            if (goodsIds == null) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            TemplateCommoditySearchRequest request = new TemplateCommoditySearchRequest();
            request.setCurrent(dto.getCurrent());
            request.setPageSize(dto.getPageSize());
            request.setShopId(dto.getShopId());
            request.setCategoryId(dto.getCategoryId());
            request.setBrandId(dto.getBrandId());
            request.setMemberName(dto.getSupplyName());
            request.setName(dto.getGoodsName());
            request.setIdInList(goodsIds);
            request.setPriceTypeList(Stream.of(PriceTypeEnum.Cash.getCode()).collect(Collectors.toList()));
            wrapper = templateFeign.searchCommodityList(request);
        }

        //校验返回结果
        if (wrapper == null || wrapper.getData() == null || CollectionUtil.isEmpty(wrapper.getData().getData())) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        //拼装
        return Wrapper.success(new PageData<>(wrapper.getData().getTotalCount(), wrapper.getData().getData().stream().map(goods -> {
            GoodsVO goodsVO = new GoodsVO();
            goodsVO.setGoodsId(goods.getId());
            goodsVO.setGoodsPicUrl(goods.getMainPic());
            goodsVO.setGoodsName(goods.getName());
            goodsVO.setGoodsSlogan(goods.getSlogan());
            goodsVO.setGoodsPoints(goods.getSellingPoint());
            goodsVO.setCategoryName(goods.getCustomerCategory().getName());
            goodsVO.setBrandName(goods.getBrand() != null ? goods.getBrand().getName() : null);
            goodsVO.setPriceRange(goods.getMin() + "~" + goods.getMax());
            goodsVO.setSupplier(goods.getMemberName());
            goodsVO.setPriceType(goods.getPriceType());
            goodsVO.setShopId(goods.getStoreId());
            goodsVO.setMemberId(goods.getMemberId());
            goodsVO.setMemberRoleId(goods.getMemberRoleId());
            return goodsVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 获取品牌列表
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<PageData<BrandVO>> findBrandList(RecommendDTO dto) {
        //拿到品牌ID集合
        List<Long> brandIds = dto.getBrandIdList() != null && CollectionUtil.isNotEmpty(dto.getBrandIdList()) ? dto.getBrandIdList() : null;

        /*
            调用搜索服务 -> 查询品牌信息接口:
               0.未选择 根据品牌ID查出不包含的品牌
               1.已选择 根据品牌ID查出包含的品牌
               2.所有  查出所有
        */
        Wrapper<PageData<BrandResponse>> wrapper = null;
        if (dto.getType().equals(SelectStatusEnum.UNSELECTED.getCode())) {
            wrapper = templateFeign.getBrandList(dto.getCurrent(), dto.getPageSize(), dto.getShopId(), null, null, null, null, null, dto.getBrandName(), null, brandIds);
        }
        if (dto.getType().equals(SelectStatusEnum.SELECTED.getCode())) {
            if (brandIds == null) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            wrapper = templateFeign.getBrandList(dto.getCurrent(), dto.getPageSize(), dto.getShopId(), null, null, null, null, null, null, brandIds, null);
        }
        if (dto.getType().equals(SelectStatusEnum.ALL.getCode())) {
            wrapper = templateFeign.getBrandList(dto.getCurrent(), dto.getPageSize(), null, null, null, null, null, null, null, null, null);
        }

        //校验返回结果
        if (wrapper == null || wrapper.getData() == null || CollectionUtil.isEmpty(wrapper.getData().getData())) {
            return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
        }

        //拼装
        return Wrapper.success(new PageData<>(wrapper.getData().getTotalCount(), wrapper.getData().getData().stream().map(brand -> {
            BrandVO brandVO = new BrandVO();
            brandVO.setBrandId(brand.getId());
            brandVO.setBrandLogo(brand.getLogoUrl());
            brandVO.setBrandName(brand.getName());
            return brandVO;
        }).collect(Collectors.toList())));
    }

    /**
     * 获取店铺列表
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<PageData<StoreVO>> findStoreList(RecommendDTO dto) {
        if (dto.getType().equals(SelectStatusEnum.UNSELECTED.getCode())) {
            JPAQuery<MemberShop> query=this.findMemberShop(dto);
            long totalCount = query.fetchCount();
            List<MemberShop> memberShops = query.fetch();

            if (CollectionUtil.isEmpty(memberShops)) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }

            //调用商品服务 -> 根据会员ID和角色ID集合获取店铺的主营分类
            Map<String, StoreResponse> map = commodityFeign.getCommodityAndCategoryByMemberIdAndMemberRoleId(
                    memberShops.stream().map(a -> {
                        MemberRequest memberRequest = new MemberRequest();
                        memberRequest.setMemberId(a.getMemberId());
                        memberRequest.setMemberRoleId(a.getRoleId());
                        return memberRequest;
                    }).collect(toList())
            );

            return Wrapper.success(new PageData<>(totalCount,memberShops.stream().map(a -> {
                StoreVO storeVO = new StoreVO();
                BeanUtils.copyProperties(a, storeVO);
                if (CollectionUtil.isNotEmpty(map) && map.get(a.getMemberId() + "-" + a.getRoleId()) != null) {
                    storeVO.setMainCategory(map.get(a.getMemberId() + "-" + a.getRoleId()).getCustomerCategoryName());
                }
                return storeVO;
            }).collect(Collectors.toList())));

        }
        if (dto.getType().equals(SelectStatusEnum.SELECTED.getCode())) {
            if (CollectionUtil.isEmpty(dto.getStoreIdList())) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            JPAQuery<MemberShop> query=this.findMemberShop(dto);
            long totalCount = query.fetchCount();
            List<MemberShop> memberShops = query.fetch();
            if (CollectionUtil.isEmpty(memberShops)) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            List<MemberShop> list = memberShops.stream().sorted(Comparator.comparingInt(a -> dto.getStoreIdList().indexOf(a.getId()))).collect(toList());
            //调用商品服务 -> 根据会员ID和角色ID集合获取店铺的主营分类
            Map<String, StoreResponse> map = commodityFeign.getCommodityAndCategoryByMemberIdAndMemberRoleId(
                    list.stream().map(a -> {
                        MemberRequest memberRequest = new MemberRequest();
                        memberRequest.setMemberId(a.getMemberId());
                        memberRequest.setMemberRoleId(a.getRoleId());
                        return memberRequest;
                    }).collect(toList())
            );

            return Wrapper.success(new PageData<>(totalCount, list.stream().map(a -> {
                StoreVO storeVO = new StoreVO();
                BeanUtils.copyProperties(a, storeVO);
                if (CollectionUtil.isNotEmpty(map) && map.get(a.getMemberId() + "-" + a.getRoleId()) != null) {
                    storeVO.setMainCategory(map.get(a.getMemberId() + "-" + a.getRoleId()).getCustomerCategoryName());
                }
                return storeVO;
            }).collect(Collectors.toList())));
        }

        return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
    }

    private JPAQuery<MemberShop> findMemberShop(RecommendDTO dto) {
        //查询表实体 - 店铺门户
        QMemberShop memberShop = QMemberShop.memberShop;

        //查询条件构造 - 搜索条件
        BooleanBuilder predicates = new BooleanBuilder();
        if (CollectionUtil.isNotEmpty(dto.getStoreIdList())){
            if (dto.getType().equals(SelectStatusEnum.UNSELECTED.getCode())){
                predicates.and(memberShop.id.notIn(dto.getStoreIdList()));
            }else {
                predicates.and(memberShop.id.in(dto.getStoreIdList()));
            }

        }
        if (StringUtils.isNotBlank(dto.getMemberName())){
            predicates.and(memberShop.memberName.like("%" + dto.getMemberName() + "%"));
        }

        //搜索条件 - 省编码。
        if(StringUtils.isNotBlank(dto.getProvinceCode())) {
            predicates.and(
                    memberShop.provincesCodeList.like("%" + dto.getProvinceCode() + "%")
                            .or(memberShop.provincesCodeList.eq("0"))
            );
        }
        //搜索条件 - 市编码。
        if(StringUtils.isNotBlank(dto.getCityCode())) {
            predicates.and(
                    memberShop.cityCodeList.like("%" + dto.getCityCode() + "%")
                            .or(memberShop.cityCodeList.eq("0"))
            );
        }
        //查询
        JPAQuery<MemberShop> query = jpaQueryFactory.select(memberShop).from(memberShop).where(predicates);
        query.limit(dto.getPageSize()).offset(dto.getCurrent() - 1).orderBy(memberShop.createTime.desc());
        return query;
    }

    /**
     * 获取物流列表
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<PageData<LogisticsVO>> findLogisticsList(RecommendDTO dto) {
        if (dto.getType().equals(SelectStatusEnum.UNSELECTED.getCode())) {
            Pageable pageable = PageRequest.of(dto.getCurrent() - 1, dto.getPageSize(), Sort.by("createTime").descending());
            Page<MemberLogistics> page;
            if (CollectionUtil.isNotEmpty(dto.getLogisticsIdList())) {
                page = StringUtils.isNotBlank(dto.getMemberName()) ? memberLogisticsRepository.findAllByIdNotInAndMemberNameContains(dto.getLogisticsIdList(), dto.getMemberName(), pageable) : memberLogisticsRepository.findAllByIdNotIn(dto.getLogisticsIdList(), pageable);
            } else {
                page = memberLogisticsRepository.findAll(pageable);
            }
            List<MemberLogistics> logistics = page.getContent();
            if (CollectionUtil.isEmpty(logistics)) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            return Wrapper.success(new PageData<>(page.getTotalElements(), page.getContent().stream().map(a -> {
                LogisticsVO logisticsVO = new LogisticsVO();
                BeanUtils.copyProperties(a, logisticsVO);
                if (CollectionUtil.isNotEmpty(a.getMainBusiness())) {
                    logisticsVO.setMainBusiness(StringUtils.join(a.getMainBusiness(), "|"));
                }
                return logisticsVO;
            }).collect(Collectors.toList())));

        }
        if (dto.getType().equals(SelectStatusEnum.SELECTED.getCode())) {
            if (CollectionUtil.isEmpty(dto.getLogisticsIdList())) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            Page<MemberLogistics> page = memberLogisticsRepository.findAllByIdIn(dto.getLogisticsIdList(), PageRequest.of(dto.getCurrent() - 1, dto.getPageSize()));
            List<MemberLogistics> list = page.getContent().stream().sorted(Comparator.comparingInt(a -> dto.getLogisticsIdList().indexOf(a.getId()))).collect(toList());

            return Wrapper.success(new PageData<>(page.getTotalElements(), list.stream().map(a -> {
                LogisticsVO logisticsVO = new LogisticsVO();
                BeanUtils.copyProperties(a, logisticsVO);
                if (CollectionUtil.isNotEmpty(a.getMainBusiness())) {
                    logisticsVO.setMainBusiness(StringUtils.join(a.getMainBusiness(), "|"));
                }
                return logisticsVO;
            }).collect(Collectors.toList())));
        }

        return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
    }

    /**
     * 获取加工列表
     *
     * @param dto 请求参数
     * @return 操作结果
     */
    @Override
    public Wrapper<PageData<ProcessVO>> findProcessList(RecommendDTO dto) {
        if (dto.getType().equals(SelectStatusEnum.UNSELECTED.getCode())) {
            Pageable pageable = PageRequest.of(dto.getCurrent() - 1, dto.getPageSize(), Sort.by("createTime").descending());
            Page<MemberProcess> page;
            if (CollectionUtil.isNotEmpty(dto.getProcessIdList())) {
                page = StringUtils.isNotBlank(dto.getMemberName()) ? memberProcessRepository.findAllByIdNotInAndMemberNameContains(dto.getProcessIdList(), dto.getMemberName(), pageable) : memberProcessRepository.findAllByIdNotIn(dto.getProcessIdList(), pageable);
            } else {
                page = memberProcessRepository.findAll(pageable);
            }
            List<MemberProcess> processes = page.getContent();
            if (CollectionUtil.isEmpty(processes)) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }

            return Wrapper.success(new PageData<>(page.getTotalElements(), page.getContent().stream().map(a -> {
                ProcessVO processVO = new ProcessVO();
                BeanUtils.copyProperties(a, processVO);
                List<String> firstNameList = a.getCategoryBOList().stream().map(CategoryBO::getFirstName).collect(toList());
                if (CollectionUtil.isNotEmpty(firstNameList)) {
                    processVO.setCategoryBOList(StringUtils.join(firstNameList, "|"));
                }
                return processVO;
            }).collect(Collectors.toList())));

        }
        if (dto.getType().equals(SelectStatusEnum.SELECTED.getCode())) {
            if (CollectionUtil.isEmpty(dto.getProcessIdList())) {
                return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
            }
            Page<MemberProcess> page = memberProcessRepository.findAllByIdIn(dto.getProcessIdList(), PageRequest.of(dto.getCurrent() - 1, dto.getPageSize()));
            List<MemberProcess> list = page.getContent().stream().sorted(Comparator.comparingInt(a -> dto.getProcessIdList().indexOf(a.getId()))).collect(toList());

            return Wrapper.success(new PageData<>(page.getTotalElements(), list.stream().map(a -> {
                ProcessVO processVO = new ProcessVO();
                BeanUtils.copyProperties(a, processVO);
                List<String> firstNameList = a.getCategoryBOList().stream().map(CategoryBO::getFirstName).collect(toList());
                if (CollectionUtil.isNotEmpty(firstNameList)) {
                    processVO.setCategoryBOList(StringUtils.join(firstNameList, "|"));
                }
                return processVO;
            }).collect(Collectors.toList())));
        }

        return Wrapper.success(new PageData<>(0L, new ArrayList<>()));
    }
}
